package cn.sdormitory.utils.wx;

import cn.hutool.json.JSONUtil;
import cn.sdormitory.common.utils.StringUtils;
import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author: lx
 * @date: 2023/11/15 10:35
 * @description: 微信小程序工具类
 */
@Slf4j
@Component
public class WeChatMessageSendUtil {

    @Value("${wxsmall.app_id}")
    private  String appId;
    @Value("${wxsmall.secret}")
    private  String secret;

    @Autowired
    RestTemplate restTemplate;

    @Autowired
    StringRedisTemplate redisTemplate;

    /**
     *
     * 发送小程序订阅信息
     * @param templateId    所需下发的订阅模板id
     * @param page          点击模板卡片后的跳转页面
     * @param data          模板内容
     * @return
     */
    public cn.hutool.json.JSONObject msgSend(String openId, String templateId, String page, Map<String, Object> data) throws Exception{
        cn.hutool.json.JSONObject msgResultObject = null;
        try {

            //region 获取access_token
            String accessToken = getAppletToken();
            //endregion

            //region 推送小程序信息
            String msgUrl = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + accessToken;
            // 参数处理
            Map<String, Object> params = new HashMap<>(6);
            params.put("touser", openId);
            params.put("template_id", templateId);
            params.put("page", page);
            params.put("lang", "zh_CN");
            params.put("miniprogram_state", "formal");
            params.put("data", data);
            String jsonData = JSONUtils.toJSONString(params);
            HttpEntity<String> request = new HttpEntity<>(jsonData);
            String msgResult = restTemplate.postForObject(msgUrl, request, String.class);
            msgResultObject = JSONUtil.parseObj(msgResult);

            if (!"0".equals(msgResultObject.get("errcode").toString())) {
                throw new RuntimeException("发送订阅消息失败，" + msgResultObject.get("errmsg"));
            }
            //endregion
        } catch (Exception e) {
            throw new RuntimeException("发送订阅消息失败，" + e);
        }
        //endregion
        return msgResultObject;
    }

    /**
     * 获取openId
     * @param code
     * @return
     */
    public Map<String, String> getOpenId(String code){
        //对传入code进行解密获取openid
//        LinkedMultiValueMap<String, String> params = new LinkedMultiValueMap<>();
//        params.add("appid",appId);
//        params.add("secret",secret);
        // 小程序调接口传的code
//        params.add("js_code",code);
//        params.add("grant_type","authorization_code");
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appId
                + "&secret=" + secret
                + "&js_code=" + code
                + "&grant_type=authorization_code";
        String result = restTemplate.getForObject(url, String.class);
        JSONObject jsonObject = JSON.parseObject(result);

        Map<String, String> map = new HashMap<>();
        try {
            map.put("openid", jsonObject.get("openid").toString());
            map.put("session_key", jsonObject.get("session_key").toString());
            log.info("code解密成功");
        } catch (Exception e){
            log.error("code解析失败，" + jsonObject.getString("errmsg"));
            throw new RuntimeException("code解析失败，" + jsonObject.getString("errmsg"));
        }
        return map;
    }

    /**
     * 获取小程序token
     * @return
     */
    public String getAppletToken () {
        // 先从缓存查看有没有
        String appletToken = redisTemplate.opsForValue().get("AppletToken");
        if (!StringUtils.isBlank(appletToken)) {
            return appletToken;
        }

        //设置查询参数与请求url
        MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
        queryParams.add("appid", appId);
        queryParams.add("secret", secret);
        String tokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential";
        UriComponentsBuilder tokenBuilder = UriComponentsBuilder.fromHttpUrl(tokenUrl).queryParams(queryParams);
        //获取token
        String tokenResult = restTemplate.getForObject(tokenBuilder.toUriString(), String.class);
        cn.hutool.json.JSONObject tokenObject = JSONUtil.parseObj(tokenResult);
        appletToken = tokenObject.getStr("access_token");
        if (StringUtils.isBlank(appletToken)) {
            throw new RuntimeException("小程序token获取失败，" + tokenObject.getStr("errmsg"));
        }
        //将token存到redis，有效期100分钟。官方接口返回的token有效期120分钟
        redisTemplate.opsForValue().set("AppletToken", appletToken);
        redisTemplate.expire("AppletToken", 100, TimeUnit.MINUTES);

        return appletToken;
    }
}
